home *** CD-ROM | disk | FTP | other *** search
- /*
- ==============================================================================
- WordUp Graphics Toolkit Version 5.0
- Demonstration Program 54
-
- This program demonstrates how to use the 3D library along with the polygon
- routines. It rotates a pyramid object using Gouraud shading.
-
- *** PROJECT ***
- This program requires the file WGT5_WC.LIB, and WGT3D_WC.LIB to be linked.
-
- *** DATA FILES ***
- You must have the MYTRI.3D and 3DDEMO.PAL files in your executable dir.
-
- ==============================================================================
- */
-
- #include <conio.h>
- #include <time.h>
- #include <ctype.h>
- #include <wgt5.h>
- #include <wgt3d.h>
-
- /*
- This is an interactive program and requires user to use keys to rotate
- the object:
- Keys used (on keypad):
- 7 8 : decrease/increase x rotation
- 4 5 : decrease/increase y rotation
- 1 2 : decrease/increase z rotation
- - + : decrease/increase distance
- q : quits program
- */
-
- #define HOLLOW 0 /* These are the types of polygons we can draw */
- #define SOLID 1
- #define GOURAUD 2 /* Lighted shading (not used in this demo) */
- #define SETGOURAUD 3 /* Fixed shading (vertices has fixed colors) */
-
- #define MAXPOINTS 100 /* Maximum number of points in the object */
-
- void loadobject (char *); /* Load a custom 3D object file format */
- void update_screen (void); /* Uses a dirty rectangle approach to copy
- the smallest area needed to update the
- screen. */
- void calculate_depth (void); /* Finds a depth value for each polygon, used
- to sort the polygons into a back to front
- order. */
- void sort_polys (void); /* Sorts the polygons by their depth value */
- void draw_polys (void); /* Draws the polygons from back to front */
- void clear_last (void); /* Erases the previous frame */
- void get_response (void); /* Reads keys and responds accordingly */
-
- point3d mypoints[9]; /* Contains original points of the object */
- point3d finp[9]; /* Holds all point after they have bee
- rotated with wrotatepoints. */
-
- tpolypoint mypoly[4]; /* Holds a 4 vertex polygon */
-
- short curx = 0; /* Current rotation values */
- short cury = 180;
- short curz = 180;
-
- int maxpoly = 300; /* Holds the number of polygons in the object */
- char c; /* user's response from keyboard */
-
- int sortpoly[MAXPOINTS]; /* The sorted polygon list */
- int ztotal[MAXPOINTS]; /* Depth values for each polygon */
- int faces[200][4]; /* Polygon face array. This holds 4 vertices
- for each polygon. All points are rotated
- and then the polygons are drawn from the
- resulting points using these vertices.
- This way polygons that share vertices will
- not have the same point rotated twice. */
- int facetype[200]; /* Holds the type of polygon for each face */
-
- block other; /* A background screen */
- color pal[256];
-
- typedef struct { /* Dirty rectangle structure */
- short x1;
- short y1;
- short x2; /* Used to keep track of what portion of the */
- short y2; /* screen has been changed, so we can update */
- } rect; /* the least amount of video memory */
-
- rect lastrect; /* Dirty rectangle for the last frame */
- rect thisrect; /* Dirty rectangle for current frame */
-
- short xdir = 1; /* Rotation directions (1, 0, -1) */
- short ydir = 1;
- short zdir = 1;
- short xpos = 0; /* Object positions */
- short ypos = 0;
- short zpos = 0;
- /* These are arrays to prepare for multiple objects in the next demo */
-
-
- /* Loads a custom 3D object file format. */
- /* WGT 3D Object File Format
- The following is a description of the file format used in the 3D demos.
-
- The first line contains the identification string
- "WGT 3D Object File"
-
- Then the number of points in the file is on a separate line.
- Each point is then stated, with the following format:
- x_coord y_coord z_coord sx_value sy_value
-
- With hollow and solid polygons, you can use sx as the color of the polygon.
- With Gouraud shading, sx is the color at that point.
- With Texture mapping, sx,sy is the offset into the texture bitmap.
-
- A blank line follows, and then the number of faces is on a new line.
- Each face is described as a 4 point sequence, using the points stated above.
- Point numbers start at 0.
- On the same line, a polygon type number is given.
- 0 means hollow
- 1 means solid
- 2 means lighted Gouraud (brighter closer to you)
- 3 means set Gouraud (uses value stored by the vertices above)
- 4 means texture mapped (not used in this demo)
-
- For example, to make a face with points 0-3, with set Gouraud shading,
- the line would be
- 0 1 2 3 3
-
- Here is an example image with one polygon:
-
- WGT 3D Object File
- 4
- -25 -25 50 140 0
- 25 -25 50 195 0
- 25 25 50 140 0
- -25 25 50 195 0
-
- 1
- 0 1 2 3 3
- */
- void loadobject (char *fname)
- {
- short i;
- short e;
- FILE *objfile;
- char blank[80];
-
- objfile = fopen (fname, "rt");
-
- fscanf (objfile, "%s %s %s %s\n", blank, blank, blank, blank);
-
- /* Number of points in this object */
- fscanf (objfile, "%d\n", &maxpoly);
-
-
- /* Write the points */
- for (i = 0; i < maxpoly; i++)
- fscanf (objfile, "%d %d %d %d %d\n", &mypoints[i].x, &mypoints[i].y, &mypoints[i].z,
- &mypoints[i].sx, &mypoints[i].sy);
-
- /* Number of faces in this object */
- fscanf (objfile, "\n%d\n", &maxpoly);
- for (i = 0; i < maxpoly; i++)
- {
- for (e = 0; e < 4; e++)
- fscanf (objfile, "%d ", &faces[i][e]);
- fscanf (objfile, "%d\n", &facetype[i]);
- }
- fclose (objfile);
- }
-
-
- void clear_last (void)
- {
- /* Do clipping for smallest area update */
- if (lastrect.x1 < 0)
- lastrect.x1 = 0;
- if (lastrect.x2 > 319)
- lastrect.x2 = 319;
- if (lastrect.y1 < 0)
- lastrect.y1 = 0;
- if (lastrect.y2 > 199)
- lastrect.y2 = 199;
- wsetcolor (0);
- wbar (lastrect.x1, lastrect.y1, lastrect.x2, lastrect.y2);
- /* Clear out the area that was drawn in last frame */
- }
-
-
- void update_screen (void)
- {
- if (lastrect.x1 > thisrect.x1)
- lastrect.x1 = thisrect.x1;
- if (lastrect.x2 < thisrect.x2)
- lastrect.x2 = thisrect.x2;
- if (lastrect.y1 > thisrect.y1)
- lastrect.y1 = thisrect.y1;
- if (lastrect.y2 < thisrect.y2)
- lastrect.y2 = thisrect.y2;
- /* See if the previous frame was larger in any direction. If it is, enlarge
- the area so it will copy black over the previous frame. */
-
- /* Do clipping */
- if (lastrect.x1 < 0)
- lastrect.x1 = 0;
- if (lastrect.x2 > 319)
- lastrect.x2 = 319;
- if (lastrect.y1 < 0)
- lastrect.y1 = 0;
- if (lastrect.y2 > 199)
- lastrect.y2 = 199;
-
- wcopyscreen(lastrect.x1, lastrect.y1, lastrect.x2, lastrect.y2, other,
- lastrect.x1, lastrect.y1, NULL);
- /* Copy from our second page to the visual page. */
-
- lastrect.x1 = thisrect.x1;
- lastrect.y1 = thisrect.y1;
- lastrect.x2 = thisrect.x2;
- lastrect.y2 = thisrect.y2;
- /* Make the last rectangle = current rectangle */
- }
-
-
-
- void calculate_depth (void)
- {
- short d;
- short e;
- short points; /* Total number of unique points */
-
- for (d = 0; d < maxpoly; d++)
- {
- sortpoly[d] = d;
- ztotal[d] = 0;
- ztotal[d] += finp[faces[d][0]].z;
- points = 1;
- for (e = 1; e < 4; e++)
- if (faces[d][e - 1] != faces[d][e]) /* Don't count duplicate points */
- {
- points++;
- ztotal[d] += finp[faces[d][e]].z;
- }
- ztotal[d] /= points;
- }
- }
-
-
- void sort_polys(void)
- {
- short d;
- short e;
- short temp;
-
- for (d = 0; d < maxpoly - 1; d++)
- for (e = d + 1; e < maxpoly; e++)
- {
- if (ztotal[sortpoly[e]] > ztotal[sortpoly[d]])
- {
- temp = sortpoly[e];
- sortpoly[e] = sortpoly[d];
- sortpoly[d] = temp;
- }
- }
- }
-
-
-
- void draw_polys(void)
- {
- short d;
- short e;
- short cp;
-
- for (d = 0; d < maxpoly; d++)
- {
- cp = sortpoly[d];
- for (e = 0; e < 4; e++)
- {
- mypoly[e].x = finp[faces[cp][e]].x;
- mypoly[e].y = finp[faces[cp][e]].y;
- if (facetype[cp] == SETGOURAUD)
- mypoly[e].sx = mypoints[faces[cp][e]].sx;
- else
- {
- mypoly[e].sx = 255 - (finp[faces[cp][e]].z + 80);
- if (mypoly[e].sx < 2)
- mypoly[e].sx = 2;
- if (mypoly[e].sx > 250)
- mypoly[e].sx = 250;
- }
-
- if (mypoly[e].x < thisrect.x1)
- thisrect.x1 = mypoly[e].x;
- if (mypoly[e].x > thisrect.x2)
- thisrect.x2 = mypoly[e].x;
- if (mypoly[e].y < thisrect.y1)
- thisrect.y1 = mypoly[e].y;
- if (mypoly[e].y > thisrect.y2)
- thisrect.y2 = mypoly[e].y;
- /* See if the polygon is larger than the current area to update.
- If it is, enlarge the area so all polygons fit inside. */
- }
- wsetcolor (mypoly[0].sx);
- if (facetype[cp] == HOLLOW)
- whollowpoly (mypoly, 4, 0, 0,CLOSED_POLY);
- else if (facetype[cp] == SOLID)
- wsolidpoly (mypoly, 4, 0, 0,NULL);
- else if ((facetype[cp] == GOURAUD) || (facetype[cp] == SETGOURAUD))
- wgouraudpoly (mypoly, 4, 0, 0);
- }
- }
-
-
-
- void get_response (void)
- {
- if (kbhit ())
- c = toupper (getch ());
-
- switch (c)
- {
- case '+': origin_z += 50;
- if (origin_z > 3000)
- origin_z = 3000;
- break;
- case '-': origin_z -= 50;
- if (origin_z < 200)
- origin_z = 200;
- break;
- case '8': curx += 5;
- break;
- case '7': curx -= 5;
- break;
- case '5': cury += 5;
- break;
- case '4': cury -= 5;
- break;
- case '2': curz += 5;
- break;
- case '1': curz -= 5;
- break;
- }
-
- if (curx > 359)
- curx -= 359;
- if (cury > 359)
- cury -= 359;
- if (curz > 359)
- curz -= 359;
- if (curx < 0)
- curx += 359;
- if (cury < 0)
- cury += 359;
- if (curz < 0)
- curz += 359;
- }
-
-
-
- void bounce_object (void)
- {
- xpos += xdir * 4;
- ypos += ydir * 4;
- zpos += zdir * 4;
-
- if (xpos > 400)
- xdir = -1;
- if (ypos > 200)
- ydir = -1;
- if (zpos > -100)
- zdir = -1;
-
- if (xpos < -400)
- xdir = 1;
- if (ypos < -200)
- ydir = 1;
- if (zpos < -900)
- zdir = 1;
-
- move_x = xpos;
- move_y = ypos;
- move_z = zpos;
- }
-
-
-
- void main(void)
- {
- short oldmode;
-
- if ( !vgadetected () )
- {
- printf ("Error - VGA card required for any WGT program.\n");
- exit (0);
- }
- printf ("WGT Example #54\n\n");
- printf ("A simple 3D object is shown on the screen.\n");
- printf ("You can use the following keys:.\n");
- printf ("+ Move backwards\n");
- printf ("- Move forwards\n");
- printf ("8 Increase X rotation\n");
- printf ("7 Decrease X rotation\n");
- printf ("5 Increase Y rotation\n");
- printf ("4 Decrease Y rotation\n");
- printf ("2 Increase Z rotation\n");
- printf ("1 Decrease Z rotation\n");
- printf ("q Quits the program\n");
- printf ("Turn NUMLOCK on to use the numeric keypad.\n");
- printf ("\n\nPress any key to continue.\n");
- getch();
-
-
- oldmode = wgetmode ();
- vga256 ();
-
- winit3d ();
- winitpoly (WGT_SYS.yres);
-
- other = wnewblock (0, 0, 319, 199);
- wloadpalette ("3ddemo.pal", pal);
- wsetpalette (0, 255, pal);
-
- maxpoly = 0;
- loadobject ("mytri.3d");
- wsetscreen (other);
-
- /* Main loop */
- do {
- thisrect.x1 = 319;
- thisrect.y1 = 199;
- thisrect.x2 = 0;
- thisrect.y2 = 0;
-
- clear_last ();
-
- wsetrotation (curx, cury, curz);
-
- bounce_object ();
- wrotatepoints (&mypoints, &finp, 8);
-
- calculate_depth ();
- sort_polys ();
- draw_polys ();
- get_response ();
- wretrace ();
- update_screen ();
- } while (c != 'Q');
- wdeinitpoly ();
- wsetmode (oldmode);
- }
-